package com.lyp.lease.web.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lyp.lease.common.constant.RedisConstant;
import com.lyp.lease.common.context.LoginUser;
import com.lyp.lease.common.context.LoginUserContext;
import com.lyp.lease.common.exception.LeaseException;
import com.lyp.lease.common.result.ResultCodeEnum;
import com.lyp.lease.common.utils.JwtUtil;
import com.lyp.lease.model.entity.SystemUser;
import com.lyp.lease.model.enums.BaseStatus;
import com.lyp.lease.web.admin.mapper.SystemUserMapper;
import com.lyp.lease.web.admin.service.LoginService;
import com.lyp.lease.web.admin.service.SystemUserService;
import com.lyp.lease.web.admin.vo.login.CaptchaVo;
import com.lyp.lease.web.admin.vo.login.LoginVo;
import com.lyp.lease.web.admin.vo.system.user.SystemUserInfoVo;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import io.jsonwebtoken.lang.Assert;
import lombok.extern.apachecommons.CommonsLog;
import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.UUID;
import java.util.concurrent.TimeUnit;





@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    SystemUserMapper systemUserMapper;

    @Override
    public CaptchaVo getCaptchaVo() {

        SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 4); // 宽，高，验证码字数4位
        specCaptcha.setCharType(Captcha.TYPE_DEFAULT);

        // 验证码信息
        String codeValue = specCaptcha.text().toLowerCase();  // 验证码文字，全转小写验证，不管用户输入大写小写只要字母对就行
        String key = RedisConstant.ADMIN_LOGIN_PREFIX + UUID.randomUUID();  // 存在Redis里的键
        String img = specCaptcha.toBase64(); // 验证码图片形式
        // 将验证码存到Redis中
        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
        stringStringValueOperations.set(key,codeValue,RedisConstant.ADMIN_LOGIN_CAPTCHA_TTL_SEC, TimeUnit.SECONDS);

        // 响应给前端
        CaptchaVo captchaVo = new CaptchaVo(img, key);
        return captchaVo;
    }

    @Override
    public String login(LoginVo loginVo) {
        // 1. 没有输入验证码文字，就抛异常
        if (!StringUtils.hasText(loginVo.getCaptchaCode())){
            throw  new LeaseException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_NOT_FOUND);
        }
        //Assert.hasText(loginVo.getCaptchaCode());
        // 2.校验验证码
        String codeValue = stringRedisTemplate.opsForValue().get(loginVo.getCaptchaKey());

        // 没在Redis查到，说明过期了，因为Redis存储的验证码有TTL，60秒后过期
        if (codeValue==null) throw new LeaseException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_EXPIRED);

        // 输入的与Redis中不一致
        if (!codeValue.equals(loginVo.getCaptchaCode())) throw new LeaseException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_ERROR);
        // 验证码只能用一次
        stringRedisTemplate.delete(loginVo.getCaptchaKey());

        // 3.根据用户名查询数据库，校验用户是否存在，
        LambdaQueryWrapper<SystemUser> systemUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        systemUserLambdaQueryWrapper.eq(SystemUser::getUsername, loginVo.getUsername());
        SystemUser systemUser = systemUserMapper.selectOne(systemUserLambdaQueryWrapper);
        // 账号不存在
        if (systemUser == null)  throw new LeaseException(ResultCodeEnum.ADMIN_ACCOUNT_NOT_EXIST_ERROR);

        // 4.校验用户状态，是否被禁用，被禁用不能让该用户登录
        if (systemUser.getStatus() == BaseStatus.DISABLE) throw new LeaseException(ResultCodeEnum.ADMIN_ACCOUNT_DISABLED_ERROR);


        // 5.校验用户密码
        // 二次加密才能判断，因为存的时候是二次加密过，取也要二次加密
        if (systemUser.getPassword()==null) throw new LeaseException("数据库查询的密码为空，服务器错误",201);
        System.out.println(DigestUtils.md5Hex(loginVo.getPassword()));
        if (!systemUser.getPassword().equals(DigestUtils.md5Hex(loginVo.getPassword()))) {
            throw new LeaseException(ResultCodeEnum.ADMIN_ACCOUNT_ERROR);
        }

        // 6.返回tokenId,传入用户id和用户名根据自定义的jwt工具类生成tokenid
        return JwtUtil.createToken(systemUser.getId(),systemUser.getUsername());
    }


    @Override
    public SystemUserInfoVo getSignedInUserInfo() {
        SystemUserInfoVo systemUserInfoVo = new SystemUserInfoVo();
        // 取值
        LoginUser loginUser = LoginUserContext.getLoginUser();
        SystemUser systemUser = systemUserMapper.selectById(loginUser.getUserid());
        if (systemUser==null) throw new LeaseException(ResultCodeEnum.DATA_ERROR);

        // 封装
        systemUserInfoVo.setName(loginUser.getUsername());
        systemUserInfoVo.setAvatarUrl(systemUser.getAvatarUrl());

        return systemUserInfoVo;
    }
}
